行为型-责任链模式

概念

Chain of Responsibility Pattern:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

img

无论是作用域链、原型链、express、还是DOM节点中的事件冒泡,都能从中找到职责链的影子。

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function getActiveUploadObj() {
try{
return new ActiveObject("TXFTNActiveX.FTNUpload"); // IE上传控件
}catch(e) {
return "nextSuccessor";
}
}

function getFlashUploadObj() {
if(supportFlash().f === 1) { // supportFlash见《JavaScript设计模式--迭代器模式》
var str = '<object type="application/x-shockwave-flash"></object>';
return $(str).appendTo($("body"));
}
return "nextSuccessor";
}

function getFormUploadObj() {
var str = '<input name="file" type="file" class="ui-file" />';
return $(str).appendTo($("body"));
}

var getUploadObj = getActiveUploadObj.after(getFlashUploadObj).after(getFormUploadObj);

console.log(getUploadObj());

优点

  • 一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构,由客户端负责链的创建,降低了系统的耦合度
  • 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理的引用,可简化对象的相互连接
  • 在给对象分派职责时,职责链可以给我们更多地灵活性,可以通过在运行时对该链进行动态的增加或修改来增加或改变处理一个请求的职责
  • 在系统中增加一个新的具体请求处理者时无需修改原有系统的代码,只需要在客户端重新建链即可,符合开闭原则

缺点

  • 由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理
  • 对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响,而且在进行代码调试时不太方便
  • 如果建链不当,可能会造成循环调用,将导致系统陷入死循环